/*
 * @Author: yangzonglong
 * @Date: 2021-07-19 14:33:08
 * @version: v1.0.0
 * @Descripttion: 手机版view 
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2021-10-19 15:22:13
 * @Auditor:
 */
import React, { useCallback, useImperativeHandle, forwardRef, useRef, useState, useEffect } from 'react';
import { mobleControlMap } from './data';
import { sessionStorageKey } from './config';
import { clearSession } from './utils';
import { ViewProps, ControlProps } from './interface';

import './mobile.scss';

let timeId: any = null; //定时器清除session

const splitArr = ['text'];
const hideMtArr = ['radio', 'checkbox'];
const linkType = ['input'], //能关联数据联动的控件类型 格式为关联组件和显示字段;
  linkOtherType = ['dataLinkComBox']; //能关联数据联动的控件类型 格式为query联动 不直接赋值;
let cacheList: any = {},
  cacheListOther: any = {};

const clearFlag = 'clearFlag'; //   是否需要 清 combox的值
const headMark = '_'; //有关联 的lov  name需要加标示存起来

// type ControlRefProps = { getData?(): any };

export interface MobileViewRefProps {
  validateFields(uncheck?: boolean | undefined): Record<string, any>;
}

// linkNameList 所有关联了lov的文本框的 lov 的name 数组

export const App = ({ data: _data, structure, disabled, formInfo }: ViewProps, ref: React.Ref<MobileViewRefProps>) => {
  const controlRefs = useRef<any>({});

  const [sendData, setSendData] = useState<any>({});
  const [data, setData] = useState<any>({});
  const [linkNameList, setLinkNameList] = useState<string[]>([]);
  const [linkNameListOther, setLinkNameListOther] = useState<string[]>([]);

  useEffect(() => {
    setData((prev: any) => ({ ...prev, ..._data, ...JSON.parse(sessionStorage.getItem(sessionStorageKey['lov_cachedata']) || '{}') }));
    for (let k in _data) {
      if (_data.hasOwnProperty(k) && k.indexOf(headMark) === 0) {
        setSendData((prev: any) => ({ ...prev, [k.replace(headMark, '')]: _data[k] }));
      }
    }
  }, [_data]);

  const getData = useCallback(
    (uncheck = false) => {
      const values = {};
      const refsKey = Object.keys(controlRefs.current);

      if (refsKey.length) {
        for (let item of refsKey) {
          if (controlRefs.current[item]?.getData) {
            const data = controlRefs.current[item].getData!();

            // 当前控件
            if (!uncheck) {
              const curControl = structure.list.find((control) => {
                const id = control.options?.formItemProps?.name || control.id;
                return id === item;
              });

              // 子组件校验出错，抛出错误
              if (!data && curControl?.options?.formItemProps?.required) return false;
            }

            values[item] = data;
          }
        }
      }

      let cacheSendData = {};

      for (let k in sendData) {
        cacheSendData[headMark + k] = { ...sendData[k], [clearFlag]: false };
      }

      return { ...values, ...cacheSendData };
    },
    [sendData, structure.list]
  );

  useImperativeHandle(ref, () => ({
    validateFields: getData,
  }));

  const createControl = useCallback(
    (children: ControlProps[]): any => {
      return children.map((item, index) => {
        const Control: any = mobleControlMap[item.type];
        if (!Control) return null;

        const options: any = { disabled, ...item.options, key: item.id };
        const id = options.formItemProps?.name || item.id || index;

        options.initialValue = data?.[id];
        options.ref = (ref: any) => (controlRefs.current[id] = ref);

        if (item.type === 'dataLink') {
          return (
            <Control
              getData={getData}
              onClear={() => {
                setLinkNameList((prev) => [...prev]);
                setLinkNameListOther((prev) => [...prev]);
              }}
              onClick={() => clearTimeout(timeId)}
              {...options}
            />
          );
        }

        if (item.type === 'dataLinkComBox') {
          return <Control sendData={sendData[id] || {}} {...options} />;
        }

        if (item.type === 'text' && index < children.length - 1 && hideMtArr.includes(children[index + 1]['type'])) {
          return (
            <div key={id} className="mobileViewTextBox">
              <Control {...options} />
            </div>
          );
        }

        if (
          !splitArr.includes(item.type) &&
          (index === children.length - 1 || (index < children.length - 1 && splitArr.includes(children[index + 1]['type'])))
        ) {
          return (
            <div key={id} className="mobileViewSplitBox">
              <Control {...options} />
            </div>
          );
        }

        return <Control {...options} />;
      });
    },
    [disabled, data, getData, sendData]
  );

  useEffect(() => {
    cacheList = {};
    structure?.list?.forEach((item) => {
      if (linkType.includes(item.type) && item?.options?.inputProps?.bindName && item?.options?.inputProps?.showFiled) {
        if (cacheList[item?.options?.inputProps?.bindName]) {
          cacheList[item?.options?.inputProps?.bindName].push({
            name: item.options?.formItemProps?.name,
            showFiled: item?.options?.inputProps?.showFiled,
          });
        } else {
          cacheList[item?.options?.inputProps?.bindName] = [
            { name: item.options?.formItemProps?.name, showFiled: item?.options?.inputProps?.showFiled },
          ];
        }
      }

      if (linkOtherType.includes(item.type)) {
        if (cacheListOther[item?.options?.inputProps?.bindName]) {
          cacheListOther[item?.options?.inputProps?.bindName].push({
            name: item.options?.formItemProps?.name,
          });
        } else {
          cacheListOther[item?.options?.inputProps?.bindName] = [{ name: item.options?.formItemProps?.name }];
        }
      }
    });
    setLinkNameList(Object.keys(cacheList));
    setLinkNameListOther(Object.keys(cacheListOther));
  }, [structure]);

  useEffect(() => {
    // 改变的dataLink的name
    let lov_name = sessionStorage.getItem(sessionStorageKey['lov_name']) || '';
    //
    if (linkNameList.includes(lov_name) || linkNameListOther.includes(lov_name)) {
      let showFieldName = sessionStorage.getItem(sessionStorageKey['showFieldName']) || '';
      let lov_data: any = JSON.parse(sessionStorage.getItem(sessionStorageKey['lov_data']) || '{}') || {};
      let _values = {};
      if (lov_data.id) {
        if (linkNameList.includes(lov_name)) {
          //  数据联动组件改变
          let _data: any[] = cacheList[lov_name] || [];
          _data?.forEach((element) => (_values[element.name] = lov_data[element.showFiled]));
        }

        if (linkNameListOther.includes(lov_name)) {
          //  数据联动组件改变
          let _data: any[] = cacheListOther[lov_name] || [];
          let _sendData = {};
          _data?.forEach((element) => {
            _sendData[element.name] = { ...lov_data, [clearFlag]: true };
            _values[element.name] = undefined;
          });
          setSendData((prev: any) => ({ ...prev, ..._sendData }));
        }

        setData((prev: any) => ({ ...prev, ..._values, [lov_name]: lov_data[showFieldName] }));
      } else {
        setData((prev: any) => ({ ...prev, ...JSON.parse(sessionStorage.getItem(sessionStorageKey['lov_cachedata']) || '{}') }));
      }
    } else if (sessionStorage.getItem(sessionStorageKey['showFieldName'])) {
      // lov未关联任何数据
      let showFieldName = sessionStorage.getItem(sessionStorageKey['showFieldName']) || '';
      let lov_data: any = JSON.parse(sessionStorage.getItem(sessionStorageKey['lov_data']) || '{}') || {};
      setData((prev: any) => ({ ...prev, [lov_name]: lov_data[showFieldName] }));
    }

    //滚动条
    if (structure.list?.length && document.getElementsByClassName('app-main')[0]) {
      document.getElementsByClassName('app-main')[0].scrollTop = +(sessionStorage.getItem(sessionStorageKey['scrollTop']) || 0);
    }
  }, [linkNameList, linkNameListOther, structure]);

  useEffect(() => {
    if (Object.keys(data || {}).length === 0) return;
    if (timeId) {
      clearTimeout(timeId);
      timeId = null;
    }
    timeId = setTimeout(() => {
      clearSession();
      timeId = null;
    }, 2000);
  }, [data]);

  return (
    <div className="modalStyle">
      <div className="mobileViewTitle">
        {formInfo?.formName}
        <p>{formInfo?.formDesc}</p>
      </div>
      {structure.list ? createControl(structure.list) : []}
    </div>
  );
};

export default forwardRef(App);
